<?php

namespace common\services;

use common\models\TallyArap;
use common\models\TallyAttachment;
use common\models\TallyFuture;
use common\models\TallyFutureLog;
use common\models\TallyRecord;
use Yii;
use yii\data\Pagination;
use yii\db\StaleObjectException;
use yii\helpers\ArrayHelper;
use yii\helpers\Json;

class TallyFutureServices extends BaseService
{

    /**
     * 添加一个总挂账记录
     * @param $formData
     * @return bool
     */
    public static function create($formData)
    {

        $model = new TallyFuture();
        $model->load($formData,'');
        self::formatFieldBeforeSave($model);

        if ($model->validate() && $model->save()) {
            // 处理附件增加
            self::insertAttachment($formData,$model->id);

            return $model->id;
        }else{
            Yii::error('Tally arap insert error:'.current($model->getFirstErrors()).';post:'.Json::encode($formData,JSON_UNESCAPED_UNICODE));
            self::setError(current($model->getFirstErrors()));
            return false;
        }
    }

    /**
     * @param $formData
     * @param $recId
     * @return bool
     * @notes 增加附件表
     */
    public static function insertAttachment($formData,$recId)
    {
        $attachS = explode(',', ArrayHelper::getValue($formData,'attachment',''));
        $attachS = array_filter($attachS);
        if(!empty($attachS)) {
            $data = [
                'tally_id'          => ArrayHelper::getValue($formData,'tally_id'),
                'tally_future_id'   => $recId,
                'uid'               => ArrayHelper::getValue($formData,'uid'),
            ];
            foreach ($attachS as $attach) {
                if(!$attach) continue;
                $data['file_name'] = $attach;
                $model = new TallyAttachment();
                $model->load($data,'');
                $model->save();
            }
        }
        return true;
    }


    public static function formatFieldBeforeSave($model){
        // 整理挂账类别
        $model->category_name = TallyCategoryService::getTitleGlobal($model->category_id);
        $model->category_pid    = TallyCategoryService::getPidGlobal($model->category_id);
        $model->category_ppid    = TallyCategoryService::getPidGlobal($model->category_pid);
        $model->category_pname = TallyCategoryService::getTitleGlobal($model->category_pid);
        $model->category_ppname = TallyCategoryService::getTitleGlobal($model->category_ppid);
        $model->category_route = ','.$model->category_ppid.','.$model->category_pid.','.$model->category_id.',';

        // 填充金额
        if(!$model->id) {
            $model->amount_remain = $model->amount;
        }

        // 获取账户名称
        $account_name = TallyAccountService::getTitleGlobal($model->account_id);
        if(is_null($account_name)) {
            self::setError('账户名称转换失败|请重新选择账户');
            return false ;
        }
        if($model->account_dst_id){
            $account_dst_name = TallyAccountService::getTitleGlobal($model->account_dst_id);
            $model->account_dst_name = $account_dst_name ;
        }
        $model->account_name = $account_name ;
        // 获取商家名称
        if($model->store_id) {
            $store_name = TallyStoreService::getTitleById($model->store_id);
            $model->store_name = $store_name ?: '';
        }else{
            $model->store_id = 0 ;
            $model->store_name = '' ;
        }
        // 获取项目情况
        if($model->project_id) {
            $project_name = TallyProjectService::getTitleById($model->project_id);
            $model->project_name = $project_name ?: '';
        }else{
            $model->project_id = 0 ;
            $model->project_name = '' ;
        }
        // 获取商户情况
        if($model->member_id) {
            $member_name = TallyMemberService::getTitleById($model->member_id);
            $model->member_name = $member_name ?: '';
        }else{
            $model->member_id = 0 ;
            $model->member_name = '' ;
        }

        return $model;
    }

    /**
     * 获取符合条件的所有记录 不带分页的
     * @param array $condition
     *
     * @return array
     */
    public static function getAll(array $condition=[]): array
    {
        $query = self::getQuery(null,$condition);
        $list  = $query
            ->orderBy('tally_time desc,id desc')
            ->limit(10000)
            ->asArray()
            ->all();
        return $list ?: [];
    }

    /**
     * 获取某个账本下的所有应收付记录
     * @param array $condition
     *
     * @return array|\yii\db\ActiveRecord[]
     * @desc
     */
    public static function getList(array $condition=[], $uid=null): array
    {
        $query = self::getQuery($uid,$condition);
        // 分页相关
        $count = $query->count();
        // 构造分页对象
        $pageSize = $_SERVER['PAGE_SIZE'] ?: 10 ;
        if(isset($condition['page_limie'])){
            $pageSize = $condition['page_limie'];
        }
        $pagination = new Pagination([
            'defaultPageSize' => $pageSize,
            'totalCount' => $count
        ]);
        $pagination->validatePage=false;
        $list  = $query
            ->orderBy('tally_time desc,id desc')
            ->offset($pagination->offset)
            ->limit($pagination->limit)
            ->all();
//        foreach($list as $k){
//            $list[$k]['amount_already']=$list[$k]['amount']-$list[$k]['amount_remain'];
//        }
//        $commandQuery = clone $query;
//        echo $commandQuery->createCommand()->getRawSql();
//        die;
        $list = $list ?: [];
        return [
            'data'       => $list,
            'pageInfo'   => [
                'totalCount' => intval($count) ,
                'pageSize'   => intval($pageSize)
            ]
        ];
    }



    /**
     * 返回符合查询条件的query
     * 增加逻辑 账户的筛选 转入 与 转出账户 都要包含
     * @param       $uid
     * @param array $condition
     * @param bool $accountContain 是否包含账户相关的条件处理 | 统计的时候就需要自行组装账户条件
     *
     * @return \yii\db\ActiveQuery
     * @desc
     */
    public static function getQuery($uid=null,$condition=[],$accountContain=true): \yii\db\ActiveQuery
    {
        $where = [];
        if($uid){
            $where = [
                'uid'   => $uid,
            ];
        }
        // 从DB获取
        $query = TallyFuture::find()
            ->select('*')
            ->where($where);
        // 账本ID
        $tallyId = ArrayHelper::getValue($condition,'tally_id','');
        if($tallyId){
            $query->andFilterWhere(['=','tally_id',$tallyId]);
        }
        // 账目类别
        $type = ArrayHelper::getValue($condition,'type','');
        if($type){
            $query->andFilterWhere(['=','type',$type]);
        }
        // 上个id
        $last_id = ArrayHelper::getValue($condition,'last_id','');
        if($last_id){
            $query->andFilterWhere(['>','id',$last_id]);
        }
        // 分类ID
        $categoryId = ArrayHelper::getValue($condition,'category_id','');
        if($categoryId){
            $query->andFilterWhere(['=','category_id',$categoryId]);
        }
        // 分类ID集合
        $categoryIds = ArrayHelper::getValue($condition,'category_ids','');
        if($categoryIds){
            $query->andFilterWhere(['in','category_id',explode(',',$categoryIds)]);
        }
        $category_route_like = ArrayHelper::getValue($condition,'category_route_like','');

        if($category_route_like){
            $query->andFilterWhere(['like','category_route',','.$category_route_like.',']);
        }
        if($accountContain) {
            // 账户ID
            $accountId = ArrayHelper::getValue($condition,'account_id','');
            if($accountId){
//            $query->andFilterWhere(['=','account_id',$accountId]);
                $query->andFilterWhere(['or',
                        ['account_id' => $accountId],
                        ['account_dst_id' => $accountId],
                    ]
                );
            }
            // 账户ID集合
            $accountIds = ArrayHelper::getValue($condition,'account_ids','');
            if($accountIds){
//            $query->andFilterWhere(['in','account_id',explode(',',$accountIds)]);
                $query->andFilterWhere(['or',
                        ['in','account_id', explode(',',$accountIds) ],
                        ['in','account_dst_id',explode(',',$accountIds)],
                    ]
                );
            }
        }


        $stores = ArrayHelper::getValue($condition,'stores','');
        if($stores){
            $query->andFilterWhere(['in','store_id',$stores]);
        }

        $projects = ArrayHelper::getValue($condition,'projects','');
        if($projects){
            $query->andFilterWhere(['in','project_id',$projects]);
        }

        $members = ArrayHelper::getValue($condition,'members','');
        if($members){
            $query->andFilterWhere(['in','member_id',$members]);
        }

        $accounts = ArrayHelper::getValue($condition,'accounts','');
        if($accounts){
            $query->andFilterWhere(['or',
                    ['in','account_id', $accounts ],
                    ['in','account_dst_id',$accounts],
                ]
            );
        }

//        print_r($query->createCommand()->rawSql);
//        die;
        // 商家ID
        $storeId = ArrayHelper::getValue($condition,'store_id','');
        if($storeId){
            $query->andFilterWhere(['=','store_id',$storeId]);
        }
        // 商家ID集合
        $storeIds = ArrayHelper::getValue($condition,'store_ids','');
        if($storeIds){
            $query->andFilterWhere(['in','store_id',explode(',',$storeIds)]);
        }
        // 项目ID
        $projectId = ArrayHelper::getValue($condition,'project_id','');
        if($projectId){
            $query->andFilterWhere(['=','project_id',$projectId]);
        }
        // 项目ID集合
        $projectIds = ArrayHelper::getValue($condition,'project_ids','');
        if($projectIds){
            $query->andFilterWhere(['in','project_id',explode(',',$projectIds)]);
        }
        // 成员ID
        $memberId = ArrayHelper::getValue($condition,'member_id','');
        if($memberId){
            $query->andFilterWhere(['=','member_id',$memberId]);
        }
        // 成员ID集合
        $memberIds = ArrayHelper::getValue($condition,'member_ids','');
        if($memberIds){
            $query->andFilterWhere(['in','member_id',explode(',',$memberIds)]);
        }

        // 设置默认空 方便下面做判断
        if(!isset($condition['begin_date'])) $condition['begin_date'] = '';
        if(!isset($condition['end_date'])) $condition['end_date'] = '';

        // 时间段查询 包含右时间边界
        if($condition['begin_date'] != '' && $condition['end_date'] != '') {
            $condition['end_date'] = date('Y-m-d',strtotime('+1 day',strtotime($condition['end_date'])));
            $query->andFilterWhere(['between','tally_time',$condition['begin_date'], $condition['end_date']]);
        }
        if($condition['begin_date'] !='' && $condition['end_date'] == '') {
            $query->andFilterWhere(['>','tally_time',$condition['begin_date']]);
        }
        if($condition['begin_date'] == '' && $condition['end_date'] != '') {
            $condition['end_date'] = date('Y-m-d',strtotime('+1 day',strtotime($condition['end_date'])));
            $query->andFilterWhere(['<','tally_time',$condition['end_date']]);
        }

//        print_r($query->createCommand()->rawSql);
//        die;
        // 备注关键词
        $memo = ArrayHelper::getValue($condition,'memo','');
        if($memo){
            $query->andFilterWhere(['like','memo',$memo]);
        }
        // 包含状态
        $state = ArrayHelper::getValue($condition,'state');
        if($state !== null){
            $query->andFilterWhere(['=','state',$state]);
        }
        return $query;
    }




    public static function calRelationAmount($future_id,$formData = [],$form ): bool
    {
//        self::setError('版本未更新!');
//        return false;
        $futureInfo = TallyFuture::find()->where([
            'id' => $future_id
        ])->one();
        if(!$futureInfo) {
            self::setError('预收/付记录不存在');
            return false;
        }
        $connection = Yii::$app->db->beginTransaction();
        $userRole = TallyPmService::getRole($formData['uid'],$formData['tally_id']) ;
        $formData['state'] = TallyRecord::getDefaultStateByRole($userRole,$formData['tally_id']);
        if($formData['is_refund'] == 1){
//            var_dump($futureInfo);exit;
            if($futureInfo['type'] == 10){
                $formData['type'] = 20;
                $form->type = 20;
            }else if($futureInfo['type'] == 20){
                $formData['type'] = 10;
                $form->type = 10;
            }
        }
        $bResult = TallyRecordService::create($formData);
        if(!$bResult) {
            self::setError('记录新增失败!');
            return false;
        }
        if($formData['is_refund'] == 1){
            TallyRecordService::calRelationAmount($form);
        }
        $totalAmount = ToolService::moneyFormat($futureInfo->amount);
        $alreadyAmount = TallyRecord::find()->where([
            'future_id' => $future_id,
        ])->andFilterWhere(['<>','future_id',$futureInfo['tally_record_id']])->sum('amount');
        $alreadyAmount = $alreadyAmount ?: 0;
        $remainAmount = ToolService::groupMathAdd([$totalAmount,-1*$alreadyAmount]);
        if($remainAmount < 0){
            self::setError('冲销金额超出!');
            return false;
        }
        $futureInfo->amount_remain = $remainAmount;
        if($totalAmount == $remainAmount ){
            $futureInfo->state = TallyArap::STATE_VALID;
        }else if($remainAmount > 0) {
            $futureInfo->state = TallyArap::STATE_ARAP_ING;
        }else if($remainAmount == 0) {
            $futureInfo->state = TallyArap::STATE_ARAP_OVER;
        }
        $result = $futureInfo->save();
        if(!$result){
            $connection->rollBack();
            Yii::error('Tally Future info update error:;post:'.Json::encode($formData,JSON_UNESCAPED_UNICODE));
            self::setError('更新失败');
            return false;
        }


        //修改原有记录
        $old_tall_record_info = TallyRecord::find()->where([
            'id' => $futureInfo['tally_record_id']
        ])->one();


        $old_tall_record_info->amount =$remainAmount;

        $result = $old_tall_record_info->save();

        if($result){
            $connection->commit();
            return true;
        }else{
            $connection->rollBack();
            Yii::error('Tally Future Log insert error:'.current($old_tall_record_info->getFirstErrors()).';post:'.Json::encode($formData,JSON_UNESCAPED_UNICODE));
            self::setError(current($old_tall_record_info->getFirstErrors()));
            return false;
        }
    }


    public static function delete(array $array)
    {
        $connection = Yii::$app->db->beginTransaction();

        $model = TallyFuture::find()->where($array)->one();
        try{

            $result = $model->delete();

            $taly_record_query = TallyRecord::find()->where([
                'future_id'=>$model['id']
            ])->one();
            if($taly_record_query){
                //删除所有核销记录
                $result !== false && $result = $taly_record_query->delete();
            }

            $tally_mu_record_query = TallyRecord::find()->where([
                'id'=>$model['tally_record_id']
            ])->one();
            if($tally_mu_record_query){
                $result !== false && $result = $tally_mu_record_query->delete();
            }
            //删除母单
            if($result){
                $connection->commit();
                return true;
            }else{
                $connection->rollBack();
                self::setError('不具备删除权限');
                return false ;
            }
        }catch (\Exception $e) {
            $connection->rollBack();
            self::setError('不具备删除权限');
            return false ;

        }


    }

    public static function countFuture($condition,$uid=null): array
    {
         $query = self::getQuery(null,$condition);
        $query =  TallyFuture::find()->where([
            'tally_id' => $condition['tally_id']
        ]);
        if($uid != null){
            $query = $query->andFilterWhere(['=','uid',$uid]);
        }
        // 核销完毕状态下在应收金额
        $inOverMoney = (clone $query)
            ->andFilterWhere(['=','type',TallyRecord::TYPE_IN])
            ->andFilterWhere(['=','state',TallyArap::STATE_ARAP_OVER])
            ->sum('amount');
        // 核销完毕状态下在应付金额
        $outOverMoney = (clone $query)
            ->andFilterWhere(['=','type',TallyRecord::TYPE_OUT])
            ->andFilterWhere(['=','state',TallyArap::STATE_ARAP_OVER])
            ->sum('amount');
        // 全部状态下在应收金额
        $inAllMoney = (clone $query)
            ->andFilterWhere(['=','type',TallyRecord::TYPE_IN])
            ->andFilterWhere(['>','state',TallyArap::STATE_INVALID])
//                    ->andFilterWhere(['<','state',TallyArap::STATE_ARAP_OVER])
            ->sum('amount');
        // 全部状态下在应付金额
        $outAllMoney = (clone $query)
            ->andFilterWhere(['=','type',TallyRecord::TYPE_OUT])
            ->andFilterWhere(['>','state',TallyArap::STATE_INVALID])
//                    ->andFilterWhere(['<','state',TallyArap::STATE_ARAP_OVER])
            ->sum('amount');
        // 全部状态下在已收金额
        $inRemainMoney = (clone $query)
            ->andFilterWhere(['=','type',TallyRecord::TYPE_IN])
            ->andFilterWhere(['>','state',TallyArap::STATE_INVALID])
//                    ->andFilterWhere(['<','state',TallyArap::STATE_ARAP_OVER])
            ->sum('amount_remain');
        // 全部状态下在已付金额
        $outRemainMoney = (clone $query)
            ->andFilterWhere(['=','type',TallyRecord::TYPE_OUT])
            ->andFilterWhere(['>','state',TallyArap::STATE_INVALID])
//                    ->andFilterWhere(['<','state',TallyArap::STATE_ARAP_OVER])
            ->sum('amount_remain');
        return [
            'inOver' => ToolService::moneyType($inOverMoney),
            'outOver' => ToolService::moneyType($outOverMoney),
            'inAll' => ToolService::moneyType($inAllMoney),
            'outAll' => ToolService::moneyType($outAllMoney),
            'inRemain' => ToolService::moneyType($inRemainMoney),
            'outRemain' => ToolService::moneyType($outRemainMoney),
            'inAlready' => ToolService::groupMathAdd([
                $inAllMoney, -1*$inRemainMoney
            ]),
            'outAlready' => ToolService::groupMathAdd([
                $outAllMoney,-1*$outRemainMoney
            ])
        ];
    }

    public static function countArapPeriod($condition,$uid=null)
    {
        // 区间内 应收付金额统计
        $query =  TallyFuture::find()->where([
            'tally_id' => $condition['tally_id']
        ]);
        if($uid != null){
            $query = $query->andFilterWhere(['=','uid',$uid]);
        }

        // 设置默认空 方便下面做判断
        if(!isset($condition['begin_date'])) $condition['begin_date'] = '';
        if(!isset($condition['end_date'])) $condition['end_date'] = '';

        // 时间段查询 包含右时间边界
        if($condition['begin_date'] != '' && $condition['end_date'] != '') {
            $condition['end_date'] = date('Y-m-d',strtotime('+1 day',strtotime($condition['end_date'])));
            $query->andFilterWhere(['between','tally_time',$condition['begin_date'], $condition['end_date']]);
        }
        if($condition['begin_date'] != '' && $condition['end_date'] == '') {
            $query->andFilterWhere(['>','tally_time',$condition['begin_date']]);
        }
        if($condition['begin_date'] == '' && $condition['end_date'] != '') {
            $condition['end_date'] = date('Y-m-d',strtotime('+1 day',strtotime($condition['end_date'])));
            $query->andFilterWhere(['<','tally_time',$condition['end_date']]);
        }
        // 全部状态下的应收金额
        $inAllMoney = (clone $query)
            ->andFilterWhere(['=','type',TallyRecord::TYPE_IN])
            ->andFilterWhere(['>','state',TallyArap::STATE_INVALID])
            ->sum('amount');
        // 全部状态下的应付金额
        $outAllMoney = (clone $query)
            ->andFilterWhere(['=','type',TallyRecord::TYPE_OUT])
            ->andFilterWhere(['>','state',TallyArap::STATE_INVALID])
            ->sum('amount');

        // 统计区间内核销的应收付记录 表达为 已收 已付
        $query =  TallyRecord::find()->where([
            'tally_id' => $condition['tally_id']
        ])->andFilterWhere(['<>','future_id',0]);
        if($uid != null){
            $query = $query->andFilterWhere(['=','uid',$uid]);
        }
        // 时间段查询 包含右时间边界
        if($condition['begin_date'] != '' && $condition['end_date'] != '') {
            $condition['end_date'] = date('Y-m-d',strtotime('+1 day',strtotime($condition['end_date'])));
            $query->andFilterWhere(['between','tally_time',$condition['begin_date'], $condition['end_date']]);
        }
        if($condition['begin_date'] != '' && $condition['end_date'] == '') {
            $query->andFilterWhere(['>','tally_time',$condition['begin_date']]);
        }
        if($condition['begin_date'] == '' && $condition['end_date'] != '') {
            $condition['end_date'] = date('Y-m-d',strtotime('+1 day',strtotime($condition['end_date'])));
            $query->andFilterWhere(['<','tally_time',$condition['end_date']]);
        }
        // 已核销的应收部分
        $inOverMoney = (clone $query)
            ->andFilterWhere(['=','type',TallyRecord::TYPE_IN]) // 必须是收入账单
            ->sum('amount');
        // 已核销的应付部分
        $outOverMoney = (clone $query)
            ->andFilterWhere(['=','type',TallyRecord::TYPE_OUT]) // 必须是支出账单
            ->sum('amount');
        // 返回综合数据
        return [
            'inOver' => ToolService::moneyType($inOverMoney), // 区间内已收
            'outOver' => ToolService::moneyType($outOverMoney), // 区间内已付
            'inAll' => ToolService::moneyType($inAllMoney), // 区间内应收
            'outAll' => ToolService::moneyType($outAllMoney), // 区间内应付
        ];
    }

    public static function details($id, $tallyId): array
    {
        $list = TallyRecord::find()->where([
            'future_id' => $id,
            'tally_id'=>$tallyId,
            'state' => TallyRecord::STATE_VALID
        ])->orderBy('tally_time desc')->all();
        return $list;
    }


}